package tlv;

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;

public class TlvHwBean {
	private int ver;
	private int type;
	private int papChap = 0;
	private int rsvd = 0;
	private int serialNo;
	private int reqId;
	private String userIp;
	private int userPort = 0;
	private int errCode;
	private int attrNum;
	private List<Attr> attr = new ArrayList<Attr>();
	private String secret;

	public int getVer() {
		return ver;
	}

	public void setVer(int ver) {
		this.ver = ver;
	}

	public int getType() {
		return type;
	}

	public void setType(int type) {
		this.type = type;
	}

	public int getSerialNo() {
		return serialNo;
	}

	public void setSerialNo(int serialNo) {
		this.serialNo = serialNo;
	}

	public int getReqId() {
		return reqId;
	}

	public void setReqId(int reqId) {
		this.reqId = reqId;
	}

	public String getUserIp() {
		return userIp;
	}

	public void setUserIp(String userIp) {
		this.userIp = userIp;
	}

	public int getErrCode() {
		return errCode;
	}

	public void setErrCode(int errCode) {
		this.errCode = errCode;
	}

	public int getAttrNum() {
		return attrNum;
	}

	public void setAttrNum(int attrNum) {
		this.attrNum = attrNum;
	}

	public List<Attr> getAttr() {
		return attr;
	}

	public void setAttr(List<Attr> attr) {
		this.attr = attr;
	}

	public String getSecret() {
		return secret;
	}

	public void setSecret(String secret) {
		this.secret = secret;
	}

	public TlvHwBean() {
	}

	public byte[] toByteArray() {
		int dLen = 32;
		if (!(attr == null && attr.isEmpty())) {
			for (Attr a : attr) {
				dLen += a.getAttrLen();
			}
		}
		byte[] b = new byte[dLen];
		b[0] = (byte) ver;
		b[1] = (byte) type;
		b[2] = (byte) papChap;
		b[3] = (byte) rsvd;
		b[4] = (byte) (serialNo >> 8 & 0xff);
		b[5] = (byte) (serialNo & 0xff);
		b[6] = (byte) (reqId >> 8 & 0xff);
		b[7] = (byte) (reqId & 0xff);
		byte[] ip = ipv4Address2BinaryArray(userIp);
		System.arraycopy(ip, 0, b, 8, 4);
		b[12] = (byte) (userPort >> 8 & 0xff);
		b[13] = (byte) (userPort & 0xff);
		b[14] = (byte) errCode;
		b[15] = (byte) attrNum;
		// 生成附加属性
		int t1 = 32;
		if (!(attr == null && attr.isEmpty())) {
			for (Attr a : attr) {
				b[t1] = (byte) a.getAttrType();
				b[t1 + 1] = (byte) a.getAttrLen();
				System.arraycopy(a.getAttrValue().getBytes(), 0, b, t1 + 2, a.getAttrValue().getBytes().length);
				t1 += a.getAttrLen();
			}
		}
		byte[] au = getAuthenticator(b);
		System.arraycopy(au, 0, b, 16, 16);
		return b;
	}

	private byte[] ipv4Address2BinaryArray(String ipAdd) {
		byte[] binIP = new byte[4];
		String[] strs = ipAdd.split("\\.");
		for (int i = 0; i < strs.length; i++) {
			binIP[i] = (byte) Integer.parseInt(strs[i]);
		}
		return binIP;
	}

	/**
	 * 对字符串md5加密
	 *
	 * @param str
	 * @return
	 */
	private byte[] getMD5(byte[] a) {
		try {
			// 生成一个MD5加密计算摘要
			MessageDigest md = MessageDigest.getInstance("MD5");
			// 计算md5函数
			md.update(a);
			// digest()最后确定返回md5 hash值，返回值为8为字符串。因为md5 hash值是16位的hex值，实际上就是8位的字符
			// BigInteger函数则将8位的字符串转换成16位hex值，用字符串来表示；得到字符串形式的hash值
			return md.digest();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private byte[] getAuthenticator(byte[] a) {
		byte[] b = new byte[a.length + secret.getBytes().length];
		System.arraycopy(a, 0, b, 0, a.length);
		System.arraycopy(secret.getBytes(), 0, b, a.length, secret.getBytes().length);
		return getMD5(b);
	}

	public TlvHwBean(int ver, int type, int serialNo, int reqId, String userIp, int errCode, int attrNum, List<Attr> attr,
			String secret) {
		super();
		this.ver = ver;
		this.type = type;
		this.serialNo = serialNo;
		this.reqId = reqId;
		this.userIp = userIp;
		this.errCode = errCode;
		this.attrNum = attrNum;
		this.attr = attr;
		this.secret = secret;
	}

	public TlvHwBean(int ver, int type, int papChap, int rsvd, int serialNo, int reqId, String userIp, int userPort,int errCode, int attrNum, List<Attr> attr) {
		super();
		this.ver = ver;
		this.type = type;
		this.papChap = papChap;
		this.rsvd = rsvd;
		this.serialNo = serialNo;
		this.reqId = reqId;
		this.userIp = userIp;
		this.userPort = userPort;
		this.errCode = errCode;
		this.attrNum = attrNum;
		this.attr = attr;
	}
}
